package cc.rengu.igas.cops.core.service.trans.payment;

import cc.rengu.igas.cops.common.constant.CopsParamConstant;
import cc.rengu.igas.cops.common.enums.PassTypeEnum;
import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.core.model.SignCardInfoBean;
import cc.rengu.igas.cops.core.realize.SignCardInfoService;
import cc.rengu.igas.cops.core.realize.impl.SignCardInfoServiceImpl;
import cc.rengu.igas.cops.core.service.base.ManageService;
import cc.rengu.igas.cops.facade.request.CardSignRequest;
import cc.rengu.igas.cops.facade.response.CardSignResponse;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.constant.UserSessionConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MsgTemplateCfgMapper;
import cc.rengu.oltp.service.common.dao.NonFinanceTxnMapper;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MsgTemplateCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.NonFinanceTxnMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSONObject;

import java.util.*;
import java.util.stream.Collectors;

public class CopsCardSignService extends ManageService implements TransCustomImpl {
    @Override
    protected Object bizBeforeCust() throws Exception {
        CardSignRequest cardSignRequest = new CardSignRequest();
        ConvertUtil.convertOutput(cardSignRequest);
        return cardSignRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CardSignRequest cardSignRequest = (CardSignRequest) request;
        String instId = cardSignRequest.getHeader().getInstId();
        String userId = cardSignRequest.getUserId();
        String smsVerifySeqNum = cardSignRequest.getSmsVerifySeqNum();
        String signTokenType = cardSignRequest.getSignTokenType();
        String smsCode = cardSignRequest.getSmsCode();
        String password = cardSignRequest.getPassword();
        String acctNo = cardSignRequest.getAcctNo();

        /* Step1：获取用户信息 */
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, cardSignRequest.getHeader().getSession());
        if (null == userInfo) {
            rglog.error("获取用户信息失败!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        String signInst = userService.getUserSignInst();
        String signType = userService.getUserSignType();

        /* Step2：校验三要素校验接口是否调用成功,防止越过三要素交易直接进行签约 */
        String authenticationFinishFlag = userService.getUserSessionValue(UserSessionConstant.AUTHENTICATION_FINISH_FLAG);
        if (!AppParamConstant.YES.equals(authenticationFinishFlag)) {
            rglog.info("交易流程跳跃，三要素校验接口未完成.<{}>", authenticationFinishFlag);
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }

        /* step3.校验短信流水号 */
        NonFinanceTxn nonFinanceTxn;
        if (PassTypeEnum.BANK_SIAN.getPassCode().equals(signTokenType)) {
            rglog.info("本行快捷签约，校验验证码:<{}>", signTokenType);
            SmsService smsService = new SmsServiceImpl();
            smsService.verifySmsCode(instId, SmsTypeEnum.CARD_SIGN.getSmsType(), smsCode, smsVerifySeqNum);
        } else {
            rglog.info("非本行快捷签约，验证码验证流水号：<{}>", smsVerifySeqNum);
            NonFinanceTxnMapper nonFinanceTxnMapper = new NonFinanceTxnMapperImpl();
            nonFinanceTxn = nonFinanceTxnMapper.selectNonFinanceTxnInfoByPrimaryKey(instId, smsVerifySeqNum);
            if (nonFinanceTxn == null) {
                rglog.info("非金融流水表中无该请求短信验证码交易，instId:<{}>,smsVerifySeqNum:<{}>", instId, smsVerifySeqNum);
                throw new BizException(RespCodeEnum.VERIFICATION_CODE_INVALID.getRespCode(), RespCodeEnum.VERIFICATION_CODE_INVALID.getRespDesc());
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.ORIG_NON_FINANCE_TXN, nonFinanceTxn);
            GlobalTransUtil.setCacheValue(TransCacheConstant.SMS_CHANNEL_RELATION_KEY, nonFinanceTxn.getChannelOrderId());
        }

        /* Step4:检查签约信息 */
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        List<SignAcctInfo> signAcctInfoList = signAcctInfoMapper.selectSignAcctInfoByCertInfo(instId, cardSignRequest.getCertType(), cardSignRequest.getCertNo());
        if (null != signAcctInfoList && !signAcctInfoList.isEmpty()) {
            signAcctInfoList = signAcctInfoList.stream().filter(item -> item.getSignType().equals(signType) && item.getSignInst().equals(signInst)).collect(Collectors.toList());
            /* Step4.1：判断该用户是否已经签约该银行卡 */
            Optional<SignAcctInfo> signAcctInfoOpt = signAcctInfoList.stream().filter(item -> item.getSignAcctNo().equals(acctNo) && item.getUserId().equals(userId)).findFirst();
            if (signAcctInfoOpt.isPresent()) {
                if (AppParamConstant.YES.equals(signAcctInfoOpt.get().getSignStatus())) {
                    rglog.info("该用户账号已经完成签约，signToken:<{}>,signToeknType:<{}>", signAcctInfoOpt.get().getSignToken(), signAcctInfoOpt.get().getSignTokenType());
                    throw new BizException(RespCodeEnum.EXIT_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.EXIT_SIGN_INFO_ERROR.getRespDesc());
                } else {
                    rglog.info("该用户账户存在签约记录，但签约状态为解约。signToken:<{}>,signToeknType:<{}>", signAcctInfoOpt.get().getSignToken(), signAcctInfoOpt.get().getSignTokenType());
                    /* 先将签约信息放到交易缓存中，待签约成功后直接更新签约记录即可，不再插入新的签约记录 */
                    GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_ACCT_INFO, signAcctInfoOpt.get());
                }
            }
            /* Step4.2：生成当前签约账号的签约序号 */
            signAcctInfoList = signAcctInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getSignStatus())).collect(Collectors.toList());
            if (!signAcctInfoList.isEmpty()) {
                signAcctInfoList = signAcctInfoList.stream().sorted(Comparator.comparing(SignAcctInfo::getPayIndex).reversed()).collect(Collectors.toList());
                int payIndex = signAcctInfoList.get(0).getPayIndex() + 1;
                GlobalTransUtil.setCacheValue(TransCacheConstant.PAY_INDEX, payIndex);
            }
        } else {
            rglog.debug("当前用户无签约关系,校验上送的证件类型与证件号是否与用户信息表中的一致");
            if (userInfo.getCertType().equals(cardSignRequest.getCertType()) && !userInfo.getCertNo().equals(cardSignRequest.getCertNo())) {
                rglog.info("签约上送的证件类型:<{}>,证件号:<{}>与用户信息表中的证件类型:<{}>，证件号:<{}>不一致",
                        cardSignRequest.getCertType(), cardSignRequest.getCertNo(), userInfo.getCertType(), userInfo.getCertNo());
                throw new BizException(RespCodeEnum.CERT_NO_DIFF.getRespCode(), RespCodeEnum.CERT_NO_DIFF.getRespDesc());
            }
        }

        /* Step5:用户密码设置或者校验 */
        if (StringUtil.isEmptyOrNull(userInfo.getTransPassword())) {
            rglog.info("用户未设置密码,设置密码");
            userInfo.setTransPassword(password);
            boolean updateFlag = userService.updateUserInfo(userInfo);
            if (!updateFlag) {
                rglog.error("更新用户支付支付密码信息失败,userId:<{}>", userId);
                throw new BizException(RespCodeEnum.USER_SET_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_SET_PASSWORD_ERROR.getRespDesc());
            }
        } else if (!StringUtil.isEmptyOrNull(userInfo.getTransPassword()) && !Objects.requireNonNull(signAcctInfoList).isEmpty()) {
            rglog.info("用户已设置支付密码且存在签约关系则校验用户的支付密码是否正确");
            boolean checkResult = userService.checkUserPayPassword(instId, userId, null, password);
            if (!checkResult) {
                rglog.error("用户支付密码错误,userId:<{}>", userId);
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }
        } else {
            rglog.info("用户已设置支付密码,但不存在签约关系!");
        }

        /* step6:获取签约账号相关信息 */
        SignCardInfoService cardBinCheckService = new SignCardInfoServiceImpl();
        SignCardInfoBean signCardInfo = cardBinCheckService.getSignCardInfo(cardSignRequest.getHeader().getInstId(), cardSignRequest.getAcctNo(), cardSignRequest.getSignTokenType());
        GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_CARD_INFO, signCardInfo);
        rglog.info("签约卡类型，acctType:<{}>", signCardInfo.getAcctType());

        /* step7:调用通道签约 */
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(cardSignRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, null, channelCallCfg.getBizScene(), request);

        /* step8：更新用户手机号 */
        if (StringUtil.isEmptyOrNull(userInfo.getMobileNo())) {
            userInfo.setMobileNo(cardSignRequest.getPhoneNo());
            if (!userService.updateUserInfo(userInfo)) {
                rglog.info("更新用户手机号信息失败,userId:<{}>", userId);
                throw new BizException(RespCodeEnum.USER_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.USER_STATUS_ABNORMAL.getRespDesc());
            }
        }

        /* step9：组应答报文 */
        String passwordFlag = StringUtil.isEmptyOrNull(userInfo.getTransPassword()) ? AppParamConstant.NO : AppParamConstant.YES;
        BizResponse<CardSignResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        CardSignResponse cardSignResponse = new CardSignResponse();
        cardSignResponse.setSignToken(xmlTreeUtil.getXmlTreeStringValue("signNo"));
        cardSignResponse.setPasswordFlag(passwordFlag);
        bizResponse.setResult(cardSignResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        CardSignResponse cardSignResponse = (CardSignResponse) bizResponse.getResult();
        ConvertUtil.convertInput(cardSignResponse);
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        CardSignRequest cardSignRequest = (CardSignRequest) request;
        String bizType = cardSignRequest.getHeader().getBizType();
        SignCardInfoBean signCardInfo = (SignCardInfoBean) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_CARD_INFO);
        if (null == signCardInfo) {
            rglog.error("无法获取当前签约卡的签约相关信息!");
            return null;
        }
        //业务场景代码：00-本行借卡快捷签约,01-本行贷记卡快捷签约,02-银联无卡快捷支付签约,03-网联协议支付签约
        String bizScene = null;
        if ("00".equals(bizType)) {
            if (AcctTypeEnum.BANK_DEBIT.getAcctType().equals(signCardInfo.getAcctType())) {
                bizScene = "00";
            }
            if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(signCardInfo.getAcctType())) {
                bizScene = "01";
            }
        } else if ("01".equals(bizType)) {
            bizScene = "02";
        } else if ("02".equals(bizType)) {
            bizScene = "03";
        }
        String finalBizScene = bizScene;
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals(finalBizScene)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CardSignRequest cardSignRequest = (CardSignRequest) request;
        if ("02".equals(channelCallCfg.getBizScene()) || "03".equals(channelCallCfg.getBizScene())) {
            NonFinanceTxn nonFinanceTxn = (NonFinanceTxn) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_NON_FINANCE_TXN);
            if (null == nonFinanceTxn) {
                rglog.error("银联无卡快捷或者网联协议支付签约，未查到发送短信流水，交易失败!");
                return CheckResultEnum.REFUSE;
            }
            //网联协议支付签约设置交易类别为0202
            if ("02".equals(channelCallCfg.getBizScene())) {
                xmlTreeUtil.setXmlTreeStringValue("trxCtgy", "0202");
            }
        }
        //TODO 发送短信的交易码需要根据实际通道的交易码进行替换
        if (ChannelEnum.SMPS.getChannelType().equals(channelCallCfg.getCallChannelId()) &&
                "发送短信的交易码".equals(channelCallCfg.getCallChannelTxn())) {
            //获取短信模板
            MsgTemplateCfgMapper msgTemplateCfgMapper = new MsgTemplateCfgMapperImpl();
            MsgTemplateCfg msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(channelCallCfg.getInstId(), TemplateTypeEnum.SMS_FAST_PAYMENT_SIGN_SUCC.getTemplateType());
            if (null == msgTemplateCfg) {
                msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(AppParamConstant.DEFAULT_INSTID, TemplateTypeEnum.SMS_FAST_PAYMENT_SIGN_SUCC.getTemplateType());
                if (null == msgTemplateCfg) {
                    rglog.warn("未配置签约成功后向用户发送短信通知的短信模板,不发送短信，instId:<{}>", channelCallCfg.getInstId());
                    return CheckResultEnum.NEXT;
                }
            }
            //短信内容
            rglog.debug("短信模板代码:<{}>,短信模板内容:<{}>", msgTemplateCfg.getTemplateCode(), msgTemplateCfg.getTemplateDesc());
            String smsContent = parseSmsTemplateInfo(msgTemplateCfg.getTemplateDesc(), cardSignRequest.getAcctNo());
            GlobalTransUtil.setCacheValue(TransCacheConstant.SMS_TEMPLATE_CODE, msgTemplateCfg.getTemplateCode());
            GlobalTransUtil.setCacheValue(TransCacheConstant.SMS_CONTENT, smsContent);
            List<String> phoneList = new ArrayList<>(Collections.singleton(cardSignRequest.getPhoneNo()));
            GlobalTransUtil.setCacheValue(TransCacheConstant.SMS_PHONE_NO_LIST, phoneList);
        }
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CardSignRequest cardSignRequest = (CardSignRequest) request;
        if (null != channelResponse && (ChannelEnum.ESB.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                ChannelEnum.NCQS.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.NUCC.getChannelType().equals(channelCallCfg.getCallChannelId()))) {
            //获取银行设置的默认限额配置信息
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam singleSysParam = sysParamService.getSysParamInfo(channelCallCfg.getInstId(), CopsParamConstant.OPMS_SYS_PARAM, CopsParamConstant.SINGLE_LIMIT_AMT);
            SysParam daySysParam = sysParamService.getSysParamInfo(channelCallCfg.getInstId(), CopsParamConstant.OPMS_SYS_PARAM, CopsParamConstant.DAY_LIMIT_AMT);
            SysParam noPasswordParam = sysParamService.getSysParamInfo(channelCallCfg.getInstId(), CopsParamConstant.OPMS_SYS_PARAM, CopsParamConstant.NO_PASSWD_LIMIT_AMT);
            SysParam authLimitParam = sysParamService.getSysParamInfo(channelCallCfg.getInstId(), CopsParamConstant.OPMS_SYS_PARAM, CopsParamConstant.AUTH_LIMIT_AMT);
            SignCardInfoBean signCardInfo = (SignCardInfoBean) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_CARD_INFO);
            SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
            SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
            if (null != signAcctInfo) {
                //当前卡号已有签约记录，只更新里面的签约信息即可
                signAcctInfo.setSingleLimitAmt(singleSysParam.getParamValue());
                signAcctInfo.setDayLimitAmt(daySysParam.getParamValue());
                signAcctInfo.setNoPasswordAmt(noPasswordParam.getParamValue());
                signAcctInfo.setAuthLimitAmt(authLimitParam.getParamValue());
                String payIndexString = (String) GlobalTransUtil.getCacheValue(TransCacheConstant.PAY_INDEX);
                signAcctInfo.setPayIndex(StringUtil.isEmptyOrNull(payIndexString) ? 0 : Integer.parseInt(payIndexString));
                signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (CopsParamConstant.INT_ZERO != signAcctInfoMapper.updateSignAcctInfoBySignAcctNo(signAcctInfo)) {
                    rglog.info("根据第二索引更新签约信息数据失败，signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
                    throw new BizException(RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespCode(), RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespDesc());
                }
            } else {
                signAcctInfo = new SignAcctInfo();
                UserService userService = new UserServiceImpl();
                String signInst = userService.getUserSignInst();
                String signType = userService.getUserSignType();
                if (null != signCardInfo) {
                    if (ChannelEnum.NCQS.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.NUCC.getChannelType().equals(channelCallCfg.getCallChannelId())) {
                        String signNo = xmlTreeUtil.getXmlTreeStringValue("signNo");
                        signAcctInfo = generateSignAcctInfo(signNo, signType, signInst, signCardInfo.getAcctType(), cardSignRequest, signCardInfo);
                    } else if (ChannelEnum.ESB.getChannelType().equals(channelCallCfg.getCallChannelId())) {
                        String signNo = DateUtil.getCurrentTimeStamp() + RandomUtil.getRandomInt();
                        xmlTreeUtil.setXmlTreeStringValue("signNo", signNo);
                        signAcctInfo = generateSignAcctInfo(signNo, signType, signInst, signCardInfo.getAcctType(), cardSignRequest, signCardInfo);
                    }
                    signAcctInfo.setSingleLimitAmt(singleSysParam.getParamValue());
                    signAcctInfo.setDayLimitAmt(daySysParam.getParamValue());
                    signAcctInfo.setNoPasswordAmt(noPasswordParam.getParamValue());
                    signAcctInfo.setAuthLimitAmt(authLimitParam.getParamValue());
                    if (CopsParamConstant.INT_ZERO != signAcctInfoMapper.insertSignAcctInfo(signAcctInfo)) {
                        rglog.info("插入签约信息失败，signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
                        throw new BizException(RespCodeEnum.USER_REGISTER_ERROR.getRespCode(), RespCodeEnum.USER_REGISTER_ERROR.getRespDesc());
                    }
                } else {
                    rglog.error("签约账号关联信息为空，业务处理异常!");
                    return TransStatusEnum.SYSTEM_REJECT;
                }
            }
        }
        return transStatusEnum;
    }

    /**
     * 生成签约实体
     *
     * @param signNo          签约协议号
     * @param signType        签约类型
     * @param signInst        签约主体
     * @param acctType        账户类型
     * @param cardSignRequest 请求体
     * @return 签约实体
     * @throws Exception 异常
     */
    private SignAcctInfo generateSignAcctInfo(String signNo, String signType, String signInst, String acctType, CardSignRequest cardSignRequest, SignCardInfoBean opmsBankCodeInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        SignAcctInfo signAcctInfo = new SignAcctInfo();
        ConvertUtil.convertOutput(signAcctInfo);
        signAcctInfo.setUserId(cardSignRequest.getUserId());
        signAcctInfo.setSignToken(opmsBankCodeInfo.getBankBranchCode() + "|" + signNo);
        signAcctInfo.setSignTokenType(cardSignRequest.getSignTokenType());
        signAcctInfo.setSignType(signType);
        signAcctInfo.setSignInst(signInst);
        signAcctInfo.setCardHoldName(cardSignRequest.getCardHoldName());
        signAcctInfo.setCertType(cardSignRequest.getCertType());
        signAcctInfo.setCertNo(cardSignRequest.getCertNo());
        signAcctInfo.setSignAcctType(acctType);
        String payIndexString = (String) GlobalTransUtil.getCacheValue(TransCacheConstant.PAY_INDEX);
        signAcctInfo.setPayIndex(StringUtil.isEmptyOrNull(payIndexString) ? 0 : Integer.parseInt(payIndexString));
        signAcctInfo.setSignAcctNo(cardSignRequest.getAcctNo());
        signAcctInfo.setReserveMobileNo(cardSignRequest.getPhoneNo());
        signAcctInfo.setSignBankNo(opmsBankCodeInfo.getBankBranchCode());
        signAcctInfo.setSignBankName(opmsBankCodeInfo.getBankName());
        signAcctInfo.setSignDate(DateUtil.getCurrentDate());
        signAcctInfo.setSignStatus(AppParamConstant.YES);
        signAcctInfo.setSignSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        signAcctInfo.setSignStatus(AppParamConstant.YES);
        signAcctInfo.setSignExpiryDate("20991231");
        signAcctInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return signAcctInfo;
    }

    /**
     * 动态解析短信模板生成短信内容
     *
     * @param templateDesc 短信模板内容
     * @return 短信内容
     */
    private String parseSmsTemplateInfo(String templateDesc, String acctNo) {
        StringBuilder stringBuilder = new StringBuilder();
        while (!StringUtil.isEmptyOrNull(templateDesc) && templateDesc.contains("[")) {
            int startIndex = templateDesc.indexOf("[");
            stringBuilder.append(templateDesc, 0, startIndex);
            templateDesc = templateDesc.substring(startIndex + 1);
            int endIndex = templateDesc.indexOf("]");
            stringBuilder.append(acctNo.substring(acctNo.length() - 4));
            templateDesc = templateDesc.substring(endIndex + 1);
        }
        stringBuilder.append(templateDesc);
        return stringBuilder.toString();
    }
}
